<?php

defined('BASEPATH') OR exit('No direct script access allowed');

class Account extends CI_Model
{

    /**
     * 添加用户
     * @param $data
     * @return bool
     * @throws MyException
     */
    function add($data)
    {
        // 检测用户名重复
        $exist = $this->db->where(['name' => $data['name']])->get('user')->num_rows();
        if ($exist > 0) {
            throw new MyException('用户名存在', MyException::CONFLICT);
        }

        // 用户数据
        $password = $this->passwordHash($data['password']); // 生成密码
        $userData = [
            'name' => $data['name'], 'nickName' => $data['nickName'], 'pwd' => $password,
        ];

        // 开启事务
        $this->db->trans_begin();

        // 写入用户基本信息
        $this->db->insert('user', $userData);
        $userId = $this->db->insert_id();

        // 绑定用户角色关系

       $roleData = array();
       $role=json_decode($data['role'],true)?:[];
       foreach ($role as $roleId) {
           $roleData[] = ['uid' => $userId, 'rid' => $roleId];
       }
       $roleData && $this->db->insert_batch('userRole', $roleData);

       // 绑定用户组织关系
       $deptData = [];
       $department=json_decode($data['department'],true)?:[];
       foreach ($department AS $did) {
           $deptData[] = ['uid' => $userId, 'did' => $did];
       }
       $deptData && $this->db->insert_batch('userDept', $deptData);

        // 事务提交
        if ($this->db->trans_status() === false) {
            $this->db->trans_rollback();
            return false;
        } else {
            $this->db->trans_commit();
            return true;
        }

    }

    /**
     * 修改基础信息
     * @param $uid
     * @param $nickName
     * @param $phone
     * @param $sex
     * @return bool
     */
    function updateBasic($uid, $nickName)
    {
        return $this->db->where('id', $uid)->update('user', ['nickName' => $nickName]);
    }


    /**
     * 修改用户角色
     * @param $uid
     * @param $roleId
     * @return bool
     */
    function updateRole($uid, $roleId)
    {
        // 开启事务
        $this->db->trans_begin();

        // 删除原角色
        $this->db->delete('userRole', ['uid' => $uid]);

        // 写入新角色
        $userRole = [];
        foreach ($roleId AS $i) {
            $userRole[] = ['uid' => $uid, 'rid' => $i];
        }
        $this->db->insert_batch('userRole', $userRole);

        // 事务提交
        if ($this->db->trans_status() === false) {
            $this->db->trans_rollback();
            return false;
        } else {
            $this->db->trans_commit();
            return true;
        }
    }


    /**
     * 修改用户组织
     * @param $uid
     * @param $deptId
     * @return bool
     */
    public function updateDept($uid, $deptId)
    {
        // 开启事务
        $this->db->trans_begin();

        // 删除原组织
        $this->db->delete('userDept', ['uid' => $uid]);

        // 写入新组织
        $userDept = [];
        foreach ($deptId AS $i) {
            $userDept[] = ['uid' => $uid, 'did' => $i];
        }
        $this->db->insert_batch('userDept', $userDept);

        // 事务提交
        if ($this->db->trans_status() === false) {
            $this->db->trans_rollback();
            return false;
        } else {
            $this->db->trans_commit();
            return true;
        }
    }


    /**
     * 修改密码
     * @param $oldPwd
     * @param $newPwd
     * @return bool|CI_DB_result
     * @throws MyException
     */
    public function updatePwd($oldPwd, $newPwd)
    {
        $newPwdHash = $this->passwordHash($newPwd);

        // 验证原密码
        $user = $this->db->find('user',UID,'id','pwd');
        if ($this->validPwd($oldPwd,$user['pwd'])){
            return $this->db->where('id', UID)->update('user', ['pwd' => $newPwdHash]);
        } else {
            throw new MyException('原密码错误', MyException::INPUT_ERR);
        }
    }
    /**
     * 验证密码
     *
     * @param string $pwd 输入的密码
     * @param string $saved 数据库hash值
     * @return void
     */
     function validPwd(string $pwd,string $saved):bool
     {
          return password_verify($pwd,$saved);
      }


    /**
     * 修改用户状态
     * @param $uid
     * @param $status 0 正常 1 冻结
     * @return bool|CI_DB_result
     */
    public function updateStatus(int $uid, int $status)
    {
        return $this->db->where('id', $uid)->update('user', ['status' => $status]);
    }


    /**
     * 重置密码
     * @param $uid
     * @param $newPwd
     * @return bool|CI_DB_result
     */
    function resetPwd($uid, $newPwd)
    {
        $newPwdHash = $this->passwordHash($newPwd);
        return $this->db->where('id', $uid)->update('user', ['pwd' => $newPwdHash]);
    }


    /**
     * 登陆
     * @param $username
     * @param $password
     * @return mixed
     * @throws MyException
     */
    function login($username, $password)
    {
        $user = $this->db->where('name', $username)->get('user', 1)->row_array();
        $log = ['ip' => $this->input->ip_address(), 'name' => $username, 'pwd' => $password];
        // 记录错误日志
        if (!$user) {
            $this->db->insert('loginLog', $log);
            throw new MyException('用户名或密码错误', MyException::INPUT_ERR);
        }
        // 验证用户名密码
        if (password_verify($password, $user['pwd'])) {
            if ($user['status']!=0) throw new MyException('帐号被冻结！请联系管理员',MyException::NO_RIGHTS);
            return $this->__generateToken($user);
        } else {
            // 记录错误日志
            $this->db->insert('loginLog', $log);
            throw new MyException('用户名或密码错误', MyException::INPUT_ERR);
        }
    }


    /**
     * 统一认证登陆
     * @param $openid
     * @return array
     * @throws MyException
     */
    function oauth($openid)
    {
        $table = 'user';
        $user = $this->db->where(['openid' => $openid])->get($table)->row_array();
        if (empty($user)) throw new MyException('请确认帐号绑定正确！', MyException::INPUT_ERR);
        return $this->__generateToken($user);
    }


    /**
     * 生成Token
     * @param $payload
     * @return array
     */
    private function __generateToken($payload)
    {
        $token = md5(uniqid());
        $this->db->where('id', $payload['id'])->update('user', ['token' => $token]);
        $res['token'] = $token;
        $res['id'] = $payload['id'];
        $res['name'] = $payload['nickName'];
        return $res;
    }


    /**
     * 生成hash密码
     * @param $password
     * @return bool|mixed|string
     */
    public function passwordHash($password)
    {
        return password_hash($password, PASSWORD_DEFAULT);
    }

}
